#include <stdint.h>
#include "bsp_hx711.h"
#include "bsp_systick.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

static unsigned long hx711_base[EndHX711] = {0};
volatile unsigned long hx711_data[EndHX711] = {0};

typedef struct _HX711_IO_Info {
    GPIO_TypeDef* clk_port;
    uint16_t clk_pin;
    GPIO_TypeDef* data_port;
    uint16_t data_pin;
} hx711_io_info_t;

static hx711_io_info_t HX711_IO_Info[EndHX711] = {
    {.clk_port = GPIOC, .clk_pin = GPIO_Pin_6, .data_port = GPIOC, .data_pin = GPIO_Pin_7},   // HX711_1
    {.clk_port = GPIOB, .clk_pin = GPIO_Pin_14, .data_port = GPIOB, .data_pin = GPIO_Pin_15}, // HX711_2
    {.clk_port = GPIOB, .clk_pin = GPIO_Pin_12, .data_port = GPIOB, .data_pin = GPIO_Pin_13}, // HX711_3
    {.clk_port = GPIOC, .clk_pin = GPIO_Pin_1, .data_port = GPIOC, .data_pin = GPIO_Pin_0},   // HX711_4
    {.clk_port = GPIOC, .clk_pin = GPIO_Pin_3, .data_port = GPIOC, .data_pin = GPIO_Pin_2},   // HX711_5
    {.clk_port = GPIOC, .clk_pin = GPIO_Pin_8, .data_port = GPIOC, .data_pin = GPIO_Pin_9},   // HX711_6
};

void hx711_init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    for (uint8_t i = 0; i < EndHX711; i++) {
        GPIO_InitStruct.GPIO_Pin = HX711_IO_Info[i].clk_pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(HX711_IO_Info[i].clk_port, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = HX711_IO_Info[i].data_pin;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(HX711_IO_Info[i].data_port, &GPIO_InitStruct);
        GPIO_SetBits(HX711_IO_Info[i].clk_port, HX711_IO_Info[i].clk_pin);
    }
}

unsigned long read_count(hx711_order_t order) {
    uint8_t timeout = 0;
    unsigned long count = 0;
    GPIO_SetBits(HX711_IO_Info[order].data_port, HX711_IO_Info[order].data_pin);
    Delay_us(1);
    GPIO_ResetBits(HX711_IO_Info[order].clk_port, HX711_IO_Info[order].clk_pin);
    while (GPIO_ReadInputDataBit(HX711_IO_Info[order].data_port, HX711_IO_Info[order].data_pin)) {
        timeout++;
				Delay_us(1);
        if (timeout > 25) return 0;
    }
    for (uint8_t i = 0; i < 24; i++) {
        GPIO_SetBits(HX711_IO_Info[order].clk_port, HX711_IO_Info[order].clk_pin);
        count = count << 1;
        Delay_us(1);
        GPIO_ResetBits(HX711_IO_Info[order].clk_port, HX711_IO_Info[order].clk_pin);
        if (GPIO_ReadInputDataBit(HX711_IO_Info[order].data_port, HX711_IO_Info[order].data_pin)) {
            count++;
        }
        Delay_us(1);
    }
    GPIO_SetBits(HX711_IO_Info[order].clk_port, HX711_IO_Info[order].clk_pin);
    Delay_us(1);
    GPIO_ResetBits(HX711_IO_Info[order].clk_port, HX711_IO_Info[order].clk_pin);
    return count ^ 0x800000;
}

void hx711_read_base(void) {
    for (uint8_t i = 0; i < EndHX711; i++) {
        hx711_base[(hx711_order_t)i] = read_count((hx711_order_t)i);
    }
}

void hx711_read_all(void) {
    unsigned long temp = 0;
    for (uint8_t i = 0; i < EndHX711; i++) {
        temp = read_count((hx711_order_t)i);
        if (temp > hx711_base[(hx711_order_t)i]) {
            hx711_data[(hx711_order_t)i] = temp - hx711_base[(hx711_order_t)i];
        }
    }
}
